﻿using DramaEnglish.WPF.ViewModels;
using HandyControl.Controls;
using IceCreamMachine.EventAggregators;
using IceCreamMachine.Models;
using IceCreamMachine.Services;
using IceCreamMachine.Services.impl;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using Prism.Services.Dialogs;
using System.Threading;
using System.Threading.Tasks;

namespace IceCreamMachine.ViewModels
{
    class IceCreamProcessViewModel : ViewModelBase
    {
        #region 属性
        private Tracer _tracer1 = new Tracer("");
        public Tracer Tracer1
        {
            get { return _tracer1; }
            set { SetProperty(ref _tracer1, value); }
        }

        private Tracer _tracer2 = new Tracer("");
        public Tracer Tracer2
        {
            get { return _tracer2; }
            set { SetProperty(ref _tracer2, value); }
        }

        private RawMaterial _rawMaterial =new RawMaterial(true);
        public RawMaterial RawMaterial
        {
            get {
              
                return _rawMaterial; }
            set { SetProperty(ref _rawMaterial, value); }
        }
        

        private int _leftIceCream = 100;
        public int LeftIceCream
        {
            get { return _leftIceCream; }
            set { SetProperty(ref _leftIceCream, value); }
        }

        Task task1;
        Task task2;
        ManualResetEvent resetEvent1 = new ManualResetEvent(true);
        ManualResetEvent resetEvent2 = new ManualResetEvent(true);
        CancellationTokenSource cts1 = new CancellationTokenSource();
        CancellationTokenSource cts2 = new CancellationTokenSource();
        private static readonly object Lock1 = new object();
        private static readonly object Lock2 = new object();
        #endregion

        #region 构造函数
        public IceCreamProcessViewModel(IRegionManager regionManager, IDialogService dialogService, IEventAggregator ea)
       : base(regionManager, dialogService, ea)
        {
           
            _ = EventAggregator.GetEvent<PubSubEvent<EnumMaterial>>().Subscribe((x) =>
            {
                if (x.Equals(EnumMaterial.Strawberry))
                {
                    RawMaterial.Strawberry--;
                }
                else if (x.Equals(EnumMaterial.IceCream))
                {
                    RawMaterial.IceCream--;
                }
                else if (x.Equals(EnumMaterial.Chocolates))
                {
                    RawMaterial.Chocolates--;
                }
                var min = RawMaterial.IceCream < RawMaterial.Chocolates ? RawMaterial.IceCream : RawMaterial.Chocolates;
                LeftIceCream = min < RawMaterial.Strawberry ? min : RawMaterial.Strawberry;
                if (min < 10)
                {
                    Growl.Info("该换材料了");
                }
                if (min<=0)
                {
                    cts1.Cancel();
                    cts2.Cancel();
                }
                RawMaterial.Save();
            },
ThreadOption.PublisherThread, false);
            EventAggregator.GetEvent<PubSubEvent<EnumMaterial>>().Publish(EnumMaterial.None);

        }
        #endregion




        #region 命令
        /// <summary>
        /// 加材料锁定资源
        /// </summary>
        public DelegateCommand AddRawMaterialCommand => new(() =>
        {
            try
            {

                Task.Run(() => {
                    lock (Lock1)
                    {
                        lock (Lock2)
                        {
                            Task.Delay(1000 * 5).Wait();
                            RawMaterial.IceCream = 100;
                            RawMaterial.Chocolates = 100;
                            RawMaterial.Strawberry = 100;
                            EventAggregator.GetEvent<PubSubEvent<EnumMaterial>>().Publish(EnumMaterial.None);

                        }
                    }
                });
            }
            catch (System.Exception ex)
            {
                Growl.Error(ex.Message);
            }

        });
       



        
        public DelegateCommand<string> MakeIceCreamCommand => new((p) =>
        {
            try
            {
                if (RawMaterial.Chocolates <= 0 || RawMaterial.Strawberry <= 0 || RawMaterial.IceCream<=0)
                {
                    return;
                }
                if (p.Equals("1"))
                {
                    lock (Lock2)
                    {
                        if (task1 == null)
                        {
                            task1 = Task.Run(() =>
                            {
                                var service1 = new IceCreamFactory().Create(int.Parse(p));


                                while (true)
                                {

                                    if (cts1.Token.IsCancellationRequested)
                                        break;
                                    else
                                    {
                                        resetEvent1.WaitOne();
                                        service1.MakeIceCream(Tracer1, EventAggregator);
                                    }
                                }
                            });
                        }
                        else
                        {
                            resetEvent1.Set();
                        }
                    }

                }
                else if (p.Equals("2"))
                {
                    lock (Lock2)
                    {
                        if (task2 == null)
                        {
                            task2 = Task.Run(() =>
                            {
                                var service2 = new IceCreamFactory().Create(int.Parse(p));

                                while (true)
                                {
                                    if (cts2.Token.IsCancellationRequested)
                                        break;
                                    else
                                    {
                                        resetEvent2.WaitOne();
                                        service2.MakeIceCream(Tracer2, EventAggregator);
                                    }
                                }

                            });
                        }
                        else
                        {
                            resetEvent2.Set();
                        }
                    }
                }



            }
            catch (System.Exception ex)
            {

            }

        });



        public DelegateCommand<string> StopMakeIceCreamCommand => new((p) =>
        {
            try
            {
                if (task1 != null && p.Equals("1") && task1.Status.Equals(TaskStatus.Running))
                {
                    resetEvent1.Reset();

                }
                else if (task2 != null && p.Equals("2") && task2.Status.Equals(TaskStatus.Running))
                {
                    resetEvent2.Reset();

                }
            }
            catch (System.Exception)
            {

                throw;
            }
        });
        #endregion
    }
}
